<template>
  <div>
    <div id="info">
      <h2>
        请确保你的浏览器是支持webgl,可以点击链接进行测试
        <a href="https://get.webgl.org/">这里</a>
        进行检测。如果不支持，可百度处理方案。
      </h2>
      <span class="colorPicker">
        <input type="color" id="body-color" value="#ff0000" />
        <br />
        车身
      </span>
      <span class="colorPicker">
        <input type="color" id="details-color" value="#ffffff" />
        <br />
        轮毂
      </span>
      <span class="colorPicker">
        <input type="color" id="glass-color" value="#ffffff   " />
        <br />
        玻璃
      </span>
    </div>
    <div id="container"></div>
  </div>
</template>
<script setup>
import * as THREE from 'three'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
import { onMounted } from 'vue'
let camera, scence, renderer, controls, grid
let wheels = []
const init = () => {
  const container = document.getElementById('container')
  scence = new THREE.Scene()
  scence.background = new THREE.Color(0x333333)
  camera = new THREE.PerspectiveCamera(
    40,
    window.innerWidth / window.innerHeight,
    0.1,
    100
  )
  camera.position.set(4.25, 1.4, -4.5)
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setAnimationLoop(render)
  container.appendChild(renderer.domElement)
  controls = new OrbitControls(camera, container)
  controls.enableDamping = true
  controls.maxDistance = 9
  controls.target.set(0, 0.5, 0)
  controls.update()

  scence.environment = new RGBELoader().load(
    require('@/assets/venice_sunset_1k.hdr').default
  )
  scence.environment.mapping = THREE.EquirectangularReflectionMapping

  grid = new THREE.GridHelper(20, 40, 0xffffff, 0xffffff)
  grid.material.opacity = 0.2
  grid.material.depthWrite = false
  grid.material.transparent = true
  scence.add(grid)

  const bodyMaterial = new THREE.MeshPhysicalMaterial({
    color: 0xff0000,
    metal: 1.0,
    roughness: 0.5,
    clearcoat: 1,
    clearcoatRoughness: 0.03,
    sheen: 0.5
  })
  const detailMaterial = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    metalness: 1.0,
    roughness: 0.5
  })
  const glassMaterial = new THREE.MeshPhysicalMaterial({
    color: 0xffffff,
    matelness: 0.25,
    roughness: 0,
    transmission: 1.0
  })
  document.getElementById('body-color').addEventListener('input', function () {
    bodyMaterial.color.set(this.value)
  })
  document
    .getElementById('details-color')
    .addEventListener('input', function () {
      detailMaterial.color.set(this.value)
    })
  document.getElementById('glass-color').addEventListener('input', function () {
    glassMaterial.color.set(this.value)
  })
  const shadow = new THREE.TextureLoader().load(
    require('@/assets/ferrari_ao.png')
  )
  const dracoLoader = new DRACOLoader()
  dracoLoader.setDecoderPath('decoder/')
  const loader = new GLTFLoader()
  loader.setDRACOLoader(dracoLoader)
  loader.load(require('@/assets/ferrari.glb').default, (gltf) => {
    const carModel = gltf.scene.children[0]
    carModel.getObjectByName('body').material = bodyMaterial
    carModel.getObjectByName('glass').material = glassMaterial
    carModel.getObjectByName('rim_fl').material = detailMaterial
    carModel.getObjectByName('rim_fr').material = detailMaterial
    carModel.getObjectByName('rim_rr').material = detailMaterial
    carModel.getObjectByName('rim_rl').material = detailMaterial
    wheels.push(carModel.getObjectByName('wheel_fl'))
    wheels.push(carModel.getObjectByName('wheel_fr'))
    wheels.push(carModel.getObjectByName('wheel_rr'))
    wheels.push(carModel.getObjectByName('wheel_rl'))
    const mesh = new THREE.Mesh(
      new THREE.PlaneGeometry(0.655 * 4, 1.3 * 4),
      new THREE.MeshBasicMaterial({
        map: shadow,
        blending:THREE.MultiplyBlending
      })
    )
    mesh.rotation.x = -Math.PI * 0.5
    mesh.renderOrder = 2
    carModel.add(mesh)
    scence.add(carModel)
  })
}
const render = () => {
  controls.update()
  const time = performance.now() / 1000
  grid.position.z = time % 1
  wheels.forEach((wheel) => {
    wheel.rotation.x = -time * Math.PI * 2
  })
  renderer.render(scence, camera)
}
onMounted(() => {
  init()
})
</script>

<style lang="scss">
body {
  color: #bbbbbb;
  background: #333333;
  text-align: center;
  overflow: hidden;
}
a {
  color: #08f;
}
.colorPicker {
  display: inline-block;
  margin: 0 10px;
}
</style>
